package com.definity.toolkit.data.rss;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import com.definity.toolkit.data.Author;
import com.definity.toolkit.data.Category;
import com.definity.toolkit.data.DataException;
import com.definity.toolkit.data.Entry;
import com.definity.toolkit.data.Feed;
import com.definity.toolkit.data.Image;
import com.sun.syndication.feed.synd.SyndCategory;
import com.sun.syndication.feed.synd.SyndCategoryImpl;
import com.sun.syndication.feed.synd.SyndContent;
import com.sun.syndication.feed.synd.SyndContentImpl;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndEntryImpl;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndFeedImpl;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.SyndFeedOutput;
import com.sun.syndication.io.XmlReader;

public final class RssUtils {

	@SuppressWarnings("unchecked")
	public static Feed parse(String url) throws DataException {
		SyndFeedInput input = new SyndFeedInput();
		SyndFeed syndFeed;
		try {
			syndFeed = input.build(new XmlReader(new URL(url)));
		} catch (IllegalArgumentException e) {
			throw new DataException(e.getMessage(), e);
		} catch (FeedException e) {
			throw new DataException(e.getMessage(), e);
		} catch (IOException e) {
			throw new DataException(e.getMessage(), e);
		}
		
		Feed feed = new Feed();
		feed.setTitle(get(syndFeed.getTitle()));
		feed.setCopyright(get(syndFeed.getCopyright()));
		feed.setUpdateDate(syndFeed.getPublishedDate());
		feed.setDescription(get(syndFeed.getDescription()));
		feed.setPublishedDate(syndFeed.getPublishedDate());
		feed.setLanguage(get(syndFeed.getLanguage()));
		feed.setLink(get(syndFeed.getLink()));
		
		List<SyndCategory> categories = syndFeed.getCategories();
		for (SyndCategory syndCategory : categories) {
			feed.add(new Category(get(syndCategory.getTaxonomyUri()), get(syndCategory.getName())));
		}
		
		List<String> authors = syndFeed.getAuthors();
		for (String author : authors) {
			feed.add(new Author("", get(author), ""));
		}
		
		if (syndFeed.getImage() != null) {
			Image image = new Image();
			image.setTitle(get(syndFeed.getImage().getTitle()));
			image.setDescription(get(syndFeed.getImage().getDescription()));
			image.setLink(get(syndFeed.getImage().getLink()));
			feed.setImage(image);
		}
		
		List<SyndEntry> items = syndFeed.getEntries();
		for (SyndEntry item : items) {
			Entry entry = new Entry();
			entry.setTitle(get(item.getTitle()));
			entry.setContent(get(item.getDescription().getValue()));
			entry.setLink(get(item.getLink()));
			entry.setPublishedDate(item.getPublishedDate());
			entry.setUpdateDate(item.getUpdatedDate());
			
			List<String> itemAuthors = item.getAuthors();
			for (String author : itemAuthors) {
				entry.add(new Author("", get(author), ""));
			}
			
			List<SyndCategory> entryCategories = item.getCategories();
			for (SyndCategory category : entryCategories) {
				entry.add(new Category(get(category.getTaxonomyUri()), get(category.getName())));
			}
			
			feed.add(entry);
		}
		
		return feed;
	}
	
	public static String write(Feed feed) throws DataException {
		SyndFeed syndFeed = new SyndFeedImpl();
		syndFeed.setTitle(feed.getTitle());
		syndFeed.setCopyright(feed.getCopyright());
		syndFeed.setDescription(feed.getDescription());
		syndFeed.setLanguage(feed.getLanguage());
		syndFeed.setLink(feed.getLink());
		
		List<String> syndAuthors = new ArrayList<String>();
		for (Author author : feed.getAuthor()) {
			syndAuthors.add(author.getName());
		}
		syndFeed.setAuthors(syndAuthors);
		
		List<SyndEntry> syndEntries = new ArrayList<SyndEntry>();
		for (Entry entry : feed.getEntry()) {
			SyndEntry item = new SyndEntryImpl();
			item.setTitle(entry.getTitle());
			
			SyndContent content = new SyndContentImpl();
			content.setType("text/html");
			content.setValue(entry.getContent());
			item.setDescription(content);
			
			item.setLink(entry.getLink());
			item.setPublishedDate(entry.getPublishedDate());
			item.setUpdatedDate(entry.getUpdateDate());

			List<String> syndEntryAuthors = new ArrayList<String>();
			for (Author author : feed.getAuthor()) {
				syndEntryAuthors.add(author.getName());
			}
			item.setAuthors(syndEntryAuthors);
			
			List<SyndCategory> syndCategories = new ArrayList<SyndCategory>();
			for (Category category : entry.getCategory()) {
				SyndCategoryImpl syndCategory = new SyndCategoryImpl();
				syndCategory.setName(category.getName());
				syndCategory.setTaxonomyUri(category.getLink());
				syndCategories.add(syndCategory);
			}
			item.setCategories(syndCategories);
			
			syndEntries.add(item);
		}
		
		syndFeed.setEntries(syndEntries);
		
		SyndFeedOutput out = new SyndFeedOutput();
		try {
			return out.outputString(syndFeed);
		} catch (FeedException e) {
			throw new DataException(e.getMessage(), e);
		}
	}
	
	private static String get(String text) {
		if (text == null)
			return null;
		return text.replace("\t", "").trim();
	}
	
}
